home *** CD-ROM | disk | FTP | other *** search
- /*
- * picture.c
- *
- * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- * $Id: picture.c,v 4.0.1.2 92/02/07 09:22:20 cek Exp Locker: cek $
- *
- * $Log: picture.c,v $
- * Revision 4.0.1.2 92/02/07 09:22:20 cek
- * patch6: Fixed typo in MTV error message.
- *
- * Revision 4.0.1.1 92/01/10 16:28:28 cek
- * patch3: Added check for nonexistent patial image file.
- * patch3: Fixed declaration of nrow in count_rle_rows().
- * patch3: Changed level of several error messages.
- *
- * Revision 4.0 91/07/17 14:47:00 kolb
- * Initial version.
- *
- */
- #include "rayshade.h"
- #include "picture.h"
- #include "viewing.h"
- #include "options.h"
- #include "stats.h"
-
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- #include <io.h>
- #include <fcntl.h>
- #undef URT
- #define TARGA
- #endif
-
- #ifdef URT
- unsigned char **outptr; /* Output buffer */
- static int count_rle_rows();
- #endif
-
- /*
- * Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
- * correction.
- */
- unsigned char
- correct(x)
- Float x;
- {
- /*
- * Truncate values < 0 or > 1.
- */
- if (x < 0)
- return 0;
- if (x > 1.)
- return 255;
- return (unsigned char)(x * 255.);
- }
-
- #ifdef URT
- /*
- * Open image file and write RLE header.
- */
- void
- PictureStart(argv)
- char **argv;
- {
- char gammacom[40];
-
- if (Options.framenum != Options.startframe) {
- /*
- * We've been here before;
- * write a new header and return.
- */
- rle_put_setup(&rle_dflt_hdr);
- return;
- }
- /*
- * If Appending, then we know that outfile is valid, 'cause
- * we've already read its header.
- */
- if (Options.appending) {
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- Options.pictfile = fopen(Options.imgname, "ab");
- #else
- Options.pictfile = fopen(Options.imgname, "a");
- #endif
- if (Options.pictfile == (FILE *)0)
- RLerror(RL_PANIC, "Cannot append to %s?!\n",
- Options.imgname);
- rle_dflt_hdr.rle_file = Options.pictfile;
- rle_put_init(&rle_dflt_hdr);
- } else {
- /*
- * Starting image from scatch.
- */
- if (Options.imgname) {
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- Options.pictfile = fopen(Options.imgname, "wb");
- #else
- Options.pictfile = fopen(Options.imgname, "w");
- #endif
- if (Options.pictfile == (FILE *)NULL)
- RLerror(RL_ABORT,"Cannot open %s for writing.",
- Options.imgname);
- } else
- Options.pictfile = stdout;
-
- rle_dflt_hdr.xmax = Screen.maxx;
- rle_dflt_hdr.ymax = Screen.maxy;
- rle_dflt_hdr.xmin = Screen.minx;
- rle_dflt_hdr.ymin = Screen.miny;
- rle_dflt_hdr.alpha = Options.alpha;
- if (Options.alpha)
- RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
- if (Options.exp_output) {
- RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
- rle_dflt_hdr.ncolors = 4;
- rle_putcom("exponential_data", &rle_dflt_hdr);
- }
- else
- rle_dflt_hdr.ncolors = 3;
- /*
- * Document image gamma in RLE comment area.
- * Options.gamma has been inverted.
- */
- (void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
- rle_putcom(gammacom, &rle_dflt_hdr);
- /*
- * Document command line in RLE history.
- */
- rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
- rle_dflt_hdr.rle_file = Options.pictfile;
- rle_put_setup(&rle_dflt_hdr);
- /*
- * Flush the header. If we don't, and LINDA forks off
- * a bunch of workers, strange things will happen (they'll
- * all flush the buffer when they die, and you end up with
- * lots of headers at the end of the file).
- */
- (void)fflush(rle_dflt_hdr.rle_file);
- }
-
- if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
- RLerror(RL_PANIC, "Unable to allocate image memory.\n");
- }
-
- /*
- * Read RLE header to which we are appending in order determine
- * old resolution, window location, and the like.
- */
- void
- PictureSetWindow()
- {
- if (Options.imgname == (char *)NULL)
- RLerror(RL_ABORT,
- "No partially-completed image file specified.\n");
-
- /*
- * Open image and read RLE header.
- */
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- Options.pictfile = fopen(Options.imgname, "rb");
- #else
- Options.pictfile = fopen(Options.imgname, "r");
- #endif
- if (Options.pictfile == (FILE *)NULL) {
- RLerror(RL_ABORT, "Cannot open image file %s.\n",
- Options.imgname);
- }
- rle_dflt_hdr.rle_file = Options.pictfile;
- rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
-
- /*
- * If user specified a window that does not match what's in
- * the header, complain.
- if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
- Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
- Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
- Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
- RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
- rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
- rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
- */
- /*
- * Set window.
- */
- Screen.minx = rle_dflt_hdr.xmin;
- Screen.miny = rle_dflt_hdr.ymin;
- Screen.maxx = rle_dflt_hdr.xmax;
- Screen.maxy = rle_dflt_hdr.ymax;
-
- /*
- * Set alpha. Warn the user if the alpha option doesn't reflect
- * what's already been rendered.
- */
- if (Options.alpha != rle_dflt_hdr.alpha)
- RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
- Options.imgname,
- rle_dflt_hdr.alpha ? "has" : "does not have");
-
- Options.alpha = rle_dflt_hdr.alpha;
-
- /*
- * Determine number of scanlines written to file.
- */
- Screen.miny += count_rle_rows(&rle_dflt_hdr);
- if (Screen.miny >= Screen.maxy) {
- fprintf(stderr, "\"%s\" is a complete image.\n",
- Options.imgname);
- exit(0);
- }
- fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
- Options.imgname, Screen.miny);
- (void)fclose(Options.pictfile);
- }
-
- static int
- count_rle_rows( hdr )
- rle_hdr *hdr;
- {
- rle_op **raw;
- int *nraw, y, ynext;
-
- if (rle_raw_alloc( hdr, &raw, &nraw ) < 0) {
- RLerror(RL_PANIC,
- "Unable to allocate memory in count_rle_rows.\n");
- }
-
- y = hdr->ymin;
- while ((ynext = rle_getraw( hdr, raw, nraw )) != 32768) {
- y = ynext+1;
- rle_freeraw( hdr, raw, nraw );
- }
-
- /* Free memory. */
- rle_raw_free( hdr, raw, nraw );
-
- return y - hdr->ymin;
- }
-
- /*
- * Write a scanline of output.
- * "buf" is an array of Color structures of size Screen.xsize. Each color
- * component is normalized to [0, 1.].
- */
- void
- PictureWriteLine(buf)
- Pixel *buf;
- {
- register int i, chan;
- float floats[3];
- rle_pixel pixels[4];
-
- for(i = 0; i < Screen.xsize; i++) {
- if (!Options.exp_output) {
- /*
- * Scale colors to fit unsigned char and check for
- * over/underflow.
- */
- outptr[0][i] = CORRECT(buf[i].r);
- outptr[1][i] = CORRECT(buf[i].g);
- outptr[2][i] = CORRECT(buf[i].b);
- } else {
- /*
- * Convert 3 floats to 4 unsigned chars for
- * 'exponential_data' RLE file.
- */
- floats[0] = GAMMACORRECT(buf[i].r);
- floats[1] = GAMMACORRECT(buf[i].g);
- floats[2] = GAMMACORRECT(buf[i].b);
- float_to_exp( 3, floats, pixels );
- for (chan = 0; chan <= 3; chan++)
- outptr[chan][i] = pixels[chan];
- }
- if (Options.alpha)
- /*
- * Don't gamma correct alpha channel.
- */
- outptr[-1][i] = correct(buf[i].alpha);
- }
- rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
- }
-
- /*
- * End the frame.
- */
- void
- PictureFrameEnd()
- {
- rle_puteof(&rle_dflt_hdr);
- }
-
- /*
- * Close image file.
- */
- void
- PictureEnd()
- {
- (void)fclose(Options.pictfile);
- }
-
- #else /* !URT */
-
- #ifdef TARGA
-
- #define STORE16(c,i) *((unsigned short*)(&(c)))=(i)
-
- #define HEADERSIZE 18
- #define O_COMMENTLEN 0
- #define O_MAPTYPE 1
- #define O_FILETYPE 2
- #define O_MAPORG 3
- #define O_MAPLEN 5
- #define O_MAPSIZE 7
- #define O_XORIGIN 8
- #define O_YORIGIN 10
- #define O_HSIZE 12
- #define O_VSIZE 14
- #define O_ESIZE 16
- #define O_FLAGS 17
- #define M_ORIGIN 0x20
- #define T_RAWRGB 2
-
- #include <stdlib.h>
- #include <string.h>
-
- char NameSave[256];
- char AnimImgName[256];
- static int AnimFrameNum=0;
-
- char *AnimFrameName(char *name,int num) {
-
- static char tmp[256];
- #if defined(MSDOS) || defined(__MSDOS__)
- static char path[_MAX_PATH],drive[_MAX_DRIVE],
- dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
- strcpy(path,name);
- _splitpath(path,drive,dir,fname,ext);
- if (strlen(fname)>5)
- fname[5]='\0';
- sprintf(tmp,"%s%03d",fname,num);
- tmp[8]='\0';
- strcpy(fname,tmp);
- _makepath(path,drive,dir,fname,ext);
- strcpy(tmp,path);
- #else
- sprintf(tmp,"%s.%03d",name,num);
- #endif
- return tmp;
- }
-
- void
- PictureStart(argv)
- char **argv;
- {
- unsigned char header[HEADERSIZE];
-
-
- if (Options.imgname) {
-
- strcpy(NameSave,Options.imgname);
-
- if (Options.endframe>Options.startframe) {
- strcpy(AnimImgName,AnimFrameName(Options.imgname,AnimFrameNum));
- AnimFrameNum++;
- strcpy(Options.imgname,AnimImgName);
- }
-
- if (Options.verbose)
- fprintf(Stats.fstats,"Writing Targa to: %s\n",Options.imgname);
-
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- Options.pictfile = fopen(Options.imgname, "wb");
- #else
- Options.pictfile = fopen(Options.imgname, "w");
- #endif
- if (Options.pictfile == (FILE *)NULL)
- RLerror(RL_PANIC, "Cannot open %s for writing.",
- Options.imgname);
-
- strcpy(Options.imgname,NameSave);
-
- } else {
-
- if (Options.endframe>Options.startframe) {
- RLerror(RL_PANIC, "Cannot output animation to stdout.");
- }
-
- Options.pictfile = stdout;
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- #ifdef __BORLANDC__
- setmode(fileno(Options.pictfile),O_BINARY);
- #else
- setmode(Options.pictfile->_handle,O_BINARY);
- #endif
- #endif
- }
-
- memset(header, 0, HEADERSIZE);
- header[O_COMMENTLEN]=0;
- header[O_FILETYPE]=T_RAWRGB;
- STORE16(header[O_HSIZE], Screen.xsize);
- STORE16(header[O_VSIZE], Screen.ysize);
- header[O_ESIZE]=24;
- header[O_FLAGS]=M_ORIGIN; /* Pic drawn from top to bottom */
- fwrite(header, HEADERSIZE, 1, Options.pictfile);
-
- (void)fflush(Options.pictfile);
- }
-
- void
- PictureWriteLine(buf)
- Pixel *buf;
- {
- register int i;
-
- for (i = 0; i < Screen.xsize; i++) {
- (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
- (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
- (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
- }
- (void)fflush(Options.pictfile);
- }
-
- void
- PictureFrameEnd()
- {
- (void)fclose(Options.pictfile);
- }
-
- void
- PictureEnd()
- {
- (void)fclose(Options.pictfile);
- }
-
- #else
-
- void
- PictureStart(argv)
- char **argv;
- {
- if (Options.imgname) {
- #if defined(__WATCOMC__) || defined(__BORLANDC__)
- Options.pictfile = fopen(Options.imgname, "wb");
- #else
- Options.pictfile = fopen(Options.imgname, "w");
- #endif
- if (Options.pictfile == (FILE *)NULL)
- RLerror(RL_ABORT, "Cannot open %s for writing.",
- Options.imgname);
- } else
- Options.pictfile = stdout;
-
- fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
-
- (void)fflush(Options.pictfile);
- }
-
- void
- PictureWriteLine(buf)
- Pixel *buf;
- {
- register int i;
-
- for (i = 0; i < Screen.xsize; i++) {
- (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
- (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
- (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
- }
- (void)fflush(Options.pictfile);
- }
-
- void
- PictureFrameEnd()
- {
- /*
- * Don't do anything -- generic format has no end-of-image marker.
- */
- }
-
- void
- PictureEnd()
- {
- (void)fclose(Options.pictfile);
- }
-
- #endif
-
- #endif /* URT */
-